package com.fingard.dsp.bank.directbank.citic05;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.citic.openbank.configuration.OpenBankSdkConfiguration;
import com.citic.openbank.sdk.API;
import com.citic.openbank.sdk.CiticSdk;
import com.citic.openbank.sdk.CiticSdkInterface;
import com.citic.openbank.sdk.RequestHeader;
import com.citicbank.cbframework.common.util.CBConverter;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.IBatPayRec;
//import com.fingard.dsp.bank.directbank.citic05.util.API;
import com.fingard.dsp.bank.directbank.citic05.util.FileCompressUtil;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.detail.RetAtsBatPayRecDetail;
import com.fingard.io.FileHelper;
import com.fingard.text.StringHelper;

import java.io.BufferedReader;
import java.io.File;
import java.io.StringReader;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;

import static com.fingard.dsp.bank.helpers.YBTHelper.getBatSeqNo;

public class CITIC05BatPayRec extends CITIC05Base implements IBatPayRec {
    @Override
    public RetAtsBatPayRec d_1988_BatPay(ReqBatPayRec p_req1988) throws Exception {
        return null;
    }

    @Override
    public RetAtsQryBatPayRec d_1998_QryBatPay(ReqQryBatPayRec p_req1998) throws Exception {
        return null;
    }

    @Override
    public RetAtsBatPayRec d_9188_BatPay(ReqBatPayRec p_req9188) throws Exception {
        RetAtsBatPayRec retAts = new RetAtsBatPayRec(p_req9188.reqHeader);
        retAts.reqSeqID = p_req9188.reqBatchNO;
        String ownAct = p_req9188.ownAct;

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(ownAct, "");
            if (actItem == null) {
                retAts.respCode = "0";
                retAts.respInfo = "未找到账号[" + ownAct + "]商户配置信息";
                retAts.reqSeqID = p_req9188.reqBatchNO;
                retAts.transState = PaymentState.FAIL_Batch;
                retAts.payInfoCode = FailCode.E9981;
                retAts.writeRetToATS();
                return retAts;
            }

            // 批量代收请求文件内容
            StringBuilder sbFileContent = new StringBuilder();
            // 批次号映射文件内容，以资金批次号命名，文件内容为发送银行的批次号（0001~0500）
            StringBuilder batNoMappingContent = new StringBuilder();

            String tmpLocalMarkPath = getDataFileDirectory(p_req9188.getPayDateTime()) + File.separator + "batrec";
            String seqNo = getBatSeqNo(tmpLocalMarkPath, 4);

            int serino = 0;
            while (p_req9188.readRecord()) {
                if (batNoMappingContent.length() > 0) {
                    batNoMappingContent.append("\r\n");
                }
                if (sbFileContent.length() > 0) {
                    sbFileContent.append("\r\n");
                }
                serino++;
                String seqNoId = String.format("%06d", serino);
                String payName = p_req9188.readedDetail.payName;
                String payAct = p_req9188.readedDetail.payAct;
                String phone = p_req9188.readedDetail.cellPhone;
                String cardFlag = "";
                String sameBnk = "";
                if ("1".equals(p_req9188.readedDetail.sameBnk)) {
                    sameBnk = "1";
                } else {
                    sameBnk = "2";
                }
                String isPrivate = "";
                if ("1".equals(p_req9188.readedDetail.isPrivate)) {
                    isPrivate = "1";
                } else {
                    isPrivate = "2";
                }
                cardFlag = sameBnk + isPrivate;
                String certType = convertCertTypeToBank(p_req9188.readedDetail.certType);
                String certNum = p_req9188.readedDetail.certNum;
                String payAmount = p_req9188.readedDetail.payAmount;
                String authCode = p_req9188.readedDetail.authCode;

                // 序号|付款方名称|付款方账号|付款方手机号|交易账号标识|证件类型|有效证件号码|付款金额|商户与付款人协议编号|客户协议编号
                sbFileContent.append(MessageFormat.format("{0}|{1}|{2}|{3}|{4}|{5}|{6}|{7}|{8}|", seqNoId, payName, payAct, phone, cardFlag, certType, certNum, payAmount, authCode));
                batNoMappingContent.append(p_req9188.readedDetail.askNumber).append(",").append(seqNoId);
            }
            String tmpFileContent = sbFileContent.toString();

            //批次号映射文件处理
            String tmpUploadFileName = p_req9188.reqBatchNO + ".txt";
            String tmpUploadFilePath = tmpLocalMarkPath + File.separator + tmpUploadFileName;
            String tmpBatNoMappingContent = batNoMappingContent.toString();
            WriteBankLogLn2("批次号映射文件保存本地路径: " + tmpUploadFilePath);
            WriteBankLogLn2("批次号映射文件内容: " + tmpBatNoMappingContent);
            FileHelper.writeFile(tmpUploadFilePath, tmpBatNoMappingContent, getCharset());

            //批量代付请求文件
            String institution = getBankConfig().getValueAsString("institution");
            String date = Format.Date8Format.format(p_req9188.getPayDateTime());
            String fileName = "F" + institution + "_S5IP_001_ZLDS_" + date + actItem.recAgNum + seqNo + ".REQ";
            WriteBankLogLn2("批次请求文件内容: " + tmpFileContent);
            //business代表文本明文内容
            String fileBase64Str = null;
            //先把文件内容转为utf8的二进制，再压缩
            byte[] combyte = FileCompressUtil.compress(tmpFileContent.getBytes(getCharset()));
            //压缩后的二进制转为base64，再转为字符串
            fileBase64Str = CBConverter.bytesToBase64(combyte);

            CITIC05Header bankHeader = new CITIC05Header();
            bankHeader.openTransCode = "IFOPS006";
            bankHeader.openMerFlowId = p_req9188.reqBatchNO;

            CiticSdkInterface sdk = CiticSdk.getInstance();
            setKeys(sdk, actItem);
            setConfiguration(sdk, actItem);
            RequestHeader header = new RequestHeader();
            writeCommonHeader(header, bankHeader, actItem);
            JSONObject jsonRequest = new JSONObject();
            jsonRequest.put("sndseqno", p_req9188.reqBatchNO);
            jsonRequest.put("mrchname", actItem.userCode);
            jsonRequest.put("mrchtype", actItem.userFlag);
            jsonRequest.put("mccprtcno", actItem.recAgNum);
            jsonRequest.put("totamt", p_req9188.totalAmt);
            jsonRequest.put("totnum", p_req9188.totalNum);
            jsonRequest.put("filename", fileName);
            jsonRequest.put("filecontent", fileBase64Str);

//            String tmpStrRet = sendToBank(header, jsonRequest.toJSONString(),actItem);
            String tmpStrRet = sdk.remoteCall(header, jsonRequest.toJSONString());

            if (StringHelper.hasAnyChar(tmpStrRet)) {
                if (tmpStrRet.contains("{")) {
                    JSONObject tmpJsonResp = JSON.parseObject(tmpStrRet);
                    String retCode = tmpJsonResp.getString("RETCODE");
                    String retMsg = tmpJsonResp.getString("RETMSG");
                    retAts.respCode = "0";
                    retAts.transState = retCode;
                    retAts.payInfoCode = retCode;
                    retAts.respInfo = retMsg;
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = "银行响应数据格式非法";
                }
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = "银行响应为空";
            }
        } catch (Exception ex) {
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        retAts.writeRetToATS();
        return retAts;
    }

    @Override
    public RetAtsQryBatPayRec d_9198_QryBatPay(ReqQryBatPayRec p_req9198) throws Exception {
        RetAtsQryBatPayRec retAts = new RetAtsQryBatPayRec(p_req9198.reqHeader);
        retAts.reqSeqID = p_req9198.reqBatchNO;

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_req9198.ownAct, "");
            if (actItem == null) {
                retAts.respCode = "-1";
                retAts.respInfo = "未找到账号[" + p_req9198.ownAct + "]商户配置信息";
                retAts.writeAfterDetail();
                return retAts;
            }

            String tmpSeqNoMappingPath = getDataFileDirectory(p_req9198.getBgnDateTime()) + File.separator + "batrec";
            File tmpSeqNoMappingDir = new File(tmpSeqNoMappingPath);
            if (tmpSeqNoMappingDir.exists()) {
                File[] tmpSeqMappingFileList = tmpSeqNoMappingDir.listFiles();
                boolean isContinue = false;
                String tmpSeqMappingFileName = "";
                for (File tmpSeqMappingFile : tmpSeqMappingFileList) {
                    if (tmpSeqMappingFile.getName().contains(p_req9198.reqBatchNO)) {
                        isContinue = true;
                        tmpSeqMappingFileName = tmpSeqMappingFile.getName();
                        break;
                    }
                }
                if (isContinue) {
                    String tmpSeqNoContent = FileHelper.readFileText(tmpSeqNoMappingPath + File.separator + tmpSeqMappingFileName, getCharset());
                    String[] tmpSeqNoArray = tmpSeqNoContent.split("\r\n");
                    Map<String, String> existSeqList = new HashMap<String, String>();
                    for (String tmpSeqNo : tmpSeqNoArray) {
                        if (StringHelper.hasAnyChar(tmpSeqNo)) {
                            String[] tempStr = tmpSeqNo.split(",");
                            existSeqList.put(tempStr[1], tempStr[0]);
                        }
                    }
                    CITIC05Header bankHeader = new CITIC05Header();
                    bankHeader.openTransCode = "IFOPS008";
                    bankHeader.openMerFlowId = getQryTransID();
                    CiticSdkInterface sdk = CiticSdk.getInstance();
                    setKeys(sdk, actItem);
                    setConfiguration(sdk, actItem);
                    RequestHeader header = new RequestHeader();
                    writeCommonHeader(header, bankHeader, actItem);
                    JSONObject jsonRequest = new JSONObject();
                    jsonRequest.put("sndseqno", p_req9198.reqBatchNO);
                    jsonRequest.put("mccprtcno", actItem.recAgNum);
                    jsonRequest.put("orgseqno", p_req9198.reqBatchNO);
                    jsonRequest.put("trandt", Format.Date10Format.format(p_req9198.getBgnDateTime()));

//                    String tmpStrRet = sendToBank(header, jsonRequest.toJSONString(), actItem);

                    String tmpStrRet = sdk.remoteCall(header, jsonRequest.toJSONString());

                    if (StringHelper.hasAnyChar(tmpStrRet)) {
                        if (tmpStrRet.contains("{")) {
                            JSONObject tmpJsonResp = JSON.parseObject(tmpStrRet);
                            String retCode = tmpJsonResp.getString("RETCODE");
                            String retMsg = tmpJsonResp.getString("RETMSG");
                            String stat = tmpJsonResp.getString("stat");
                            retAts.respCode = "0";
                            retAts.respInfo = retMsg;
                            if ("AAAAAAA".equals(retCode)) {
                                if ("00".equals(stat)) {
                                    String tmpFileContent = tmpJsonResp.getString("filecontent");
                                    //解密base64
                                    byte[] decode = CBConverter.base64ToBytes(tmpFileContent);
                                    //解压
                                    byte[] uncomp = FileCompressUtil.uncompress(decode);
                                    String fileContent = new String(uncomp, getCharset());
                                    WriteBankLogStep3(fileContent);
                                    if (StringHelper.hasAnyChar(fileContent)) {
                                        StringReader strReader = new StringReader(fileContent);
                                        BufferedReader tmpReader = new BufferedReader(strReader);
                                        while (true) {
                                            String eachline = tmpReader.readLine();
                                            if (eachline == null) {
                                                break;
                                            }
                                            if (eachline.indexOf('|') > 0) {
                                                RetAtsBatPayRecDetail tmpRetDetail = new RetAtsBatPayRecDetail();
                                                String[] detailNodes = eachline.split("\\|");
                                                if (existSeqList.containsKey(detailNodes[0])) {
                                                    tmpRetDetail.postScript = detailNodes[0];
                                                    tmpRetDetail.payName = detailNodes[1];
                                                    tmpRetDetail.payAct = detailNodes[2];
                                                    tmpRetDetail.payAmount = detailNodes[3];
                                                    tmpRetDetail.result = detailNodes[4];
                                                    tmpRetDetail.payInfoCode = detailNodes[4];
                                                    tmpRetDetail.memo = detailNodes[5];
                                                    retAts.writeRetDetail(tmpRetDetail);
                                                } else {
                                                    WriteBankLogLn("本地映射文件找不到这笔：" + eachline);
                                                }
                                            } else {
                                                retAts.respCode = "-1";
                                                retAts.respInfo = "银行返回明细数据格式非法!";
                                            }
                                        }
                                    } else {
                                        retAts.respCode = "-1";
                                        retAts.respInfo = "批量代收结果文件内容为空!";
                                    }
                                } else if ("03".equals(stat)) {
                                    retAts.transState = retCode;
                                    retAts.payInfoCode = retCode;
                                } else if ("04".equals(stat)) {
                                    if (canBeNotExist(p_req9198, retAts, 50)) {
                                        retAts.transState = retCode;
                                        retAts.payInfoCode = retCode;
                                    }
                                } else {
                                    retAts.respCode = "-1";
                                    retAts.respInfo = retMsg;
                                }
                            } else {
                                retAts.respCode = "-1";
                                retAts.respInfo = retMsg;
                            }
                        } else {
                            retAts.respCode = "-1";
                            retAts.respInfo = "银行响应数据格式非法";
                        }
                    } else {
                        retAts.respCode = "-1";
                        retAts.respInfo = "银行响应为空";
                    }
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = "本地批次流水映射文件不存在!";
                }
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = "本地批次流水映射目录不存在，未发生过批次交易!";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }
        retAts.writeAfterDetail();
        return retAts;
    }

}